package com.flink.examples.functions;

import com.flink.examples.DataSource;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import java.util.List;

/**
 * @Description Reduce算子：对数据流进行滚动聚合计算，并返回每次滚动聚合计算合并后的结果
 * @Author JL
 * @Date 2020/09/14
 * @Version V1.0
 */
public class Reduce {

    /**
     * 遍历集合，分区打印每一次滚动聚合的结果
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(4);
        List<Tuple3<String,String,Integer>> tuple3List = DataSource.getTuple3ToList();
        //注意：使用Integer进行分区时，会导致分区结果不对，转换成String类型输出key即可正确输出
        KeyedStream<Tuple3<String,String,Integer>, String> keyedStream = env.fromCollection(tuple3List).keyBy(new KeySelector<Tuple3<String,String,Integer>, String>() {
            @Override
            public String getKey(Tuple3<String, String, Integer> tuple3) throws Exception {
                //f1为性别字段,以相同f1值（性别）进行分区
                return String.valueOf(tuple3.f1);
            }
        });
        SingleOutputStreamOperator<Tuple3<String, String, Integer>> result =  keyedStream.reduce(new ReduceFunction<Tuple3<String, String, Integer>>() {
            @Override
            public Tuple3<String, String, Integer> reduce(Tuple3<String, String, Integer> t0, Tuple3<String, String, Integer> t1) throws Exception {
                int totalAge = t0.f2 + t1.f2;
                return new Tuple3<>("", t0.f1, totalAge);
            }
        });
        result.print();
        env.execute("flink Reduce job");
    }
}
/* 说明：为什么每一个分区的第一个数据对象每一个参数有值，是因为滚动聚合返回的是从第二数据对象向前叠加第一个数据对象，开始计算，所以第一个数据对象根本就不进入reduce方法;
2> (张三,man,20)
2> (,man,49)
2> (,man,79)
4> (李四,girl,24)
4> (,girl,56)
4> (,girl,74)
 */